const PICK_COLOR_RANGE_MAX = 225;

export const readCV = R.both( Boolean, R.compose( R.prop('cv'), R.curryN(1, JSON.parse) ) );

export function RectOfDrawImage(dataItem) {
  const SubRect = R.props(['x', 'y', 'width', 'height']);
  const Rect = R.compose( R.concat([0, 0]), R.props(['width', 'height']) );

  return R.converge(R.concat, [SubRect, Rect])(dataItem);
}

export const SortOf = classes => R.transduce(R.map(R.prop( R.__, classes )), R.flip(R.append), []);

function RGBAData(canvas) {
  const ctx = canvas.getContext('2d');
  return ctx.getImageData(0, 0, canvas.width, canvas.height).data;
}

function RGBData(rgbaData) {
  // 将图像数据从RGBA格式转换为RGB格式，并将数据重新排列为形状为[1, 3, 255, 255]的四维数组
  const rgbData = new Float32Array(3 * Math.pow(PICK_COLOR_RANGE_MAX, 2));
  for (let i = 0; i < Math.pow(PICK_COLOR_RANGE_MAX, 2); i++) {
    rgbData[3*i] = rgbaData[4*i] / 255;  // R
    rgbData[3*i + 1] = rgbaData[4*i + 1] / 255;  // G
    rgbData[3*i + 2] = rgbaData[4*i + 2] / 255;  // B
  }
  return rgbData;
}

const TensorOf = rgbaData => new onnx.Tensor(rgbaData, 'float32', [1, 3, PICK_COLOR_RANGE_MAX, PICK_COLOR_RANGE_MAX]);

/** Map -> 概率值数组 -> Array<[k,v]> -> 排序 -> Array<k> */
const IndexListSorted = R.compose(
  R.pluck(0),
  R.sort((a, b) => b[1] - a[1]),
  R.toPairs,
  // R.converge(R.map, [R.compose( R.flip(R.divide), R.sum ), R.identity]),
  R.map(x => 1 / (1 + Math.exp(-x))),
  R.path(['1', 'data']), /* Float32Array Probability values */
  R.head,
  Array.from,
)

export function DrawBy(imgElem, dataItem) {
  return function drawOn(canvas) {
    const ctx = canvas.getContext('2d');
    ctx.drawImage(imgElem, ...RectOfDrawImage(dataItem));
    return canvas;
  };
}

export function CanvasSizeOf({ width, height }) {
  const canvas = document.createElement('canvas');
  canvas.width = width;
  canvas.height = height;
  return canvas;
}

/** @param {onnx.InferenceSession} onnxSession  */
export function useOnnx(onnxSession, url) {
  onnxSession.loadModel(url);

  return function getIndexListSorted(canvas) {
    // RGBA 取原图范围，RGB 取固定范围
    const InputTensor = R.compose( TensorOf, RGBData, RGBAData );
    return onnxSession.run([InputTensor(canvas)]).then(IndexListSorted);
  }
}
